﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RzCorportativo.DataAccess;

namespace RzCorportativo.Lib
{
    public class Vaga
    {
        public long VagaId { get; set; }
        public int CargoId { get; set; }
        public Cargo Cargo { get; set; }
        public bool Ativo { get; set; }
        public decimal? SalarioOferecido { get; set; }
        public short Disponibilidade { get; set; }
        public DateTime DataCadastro { get; set; }
        public short QtdVagas { get; set; }
        public short Status { get; set; }
        public long UsuarioId { get; set; }
        public Usuario Usuario { get; set; }
        public DateTime DataInicioInscricao { get; set; }
        public DateTime DataFimInscricao { get; set; }
        public string TipoVaga { get; set; }
        public string Observacoes { get; set; }
        public bool IsNew
        {
            get { return this.VagaId == 0; }
        }

        public bool Salvar()
        {
            DataAccess.Vaga vaga = null;
            var result = false;
            Transaction.Begin(context =>
            {
                if (this.IsNew)
                {
                    this.DataCadastro = DateTime.Now;
                    vaga = this.Insert(context);
                }
                else
                {
                    vaga = this.Update(context);
                }
                return true;
            }).OnError(ex =>
            {
            }).OnSuccess(() =>
            {
                this.VagaId = vaga.VagaId;
                result = true;
            });
            return result;
        }

        private DataAccess.Vaga Insert(DataAccess.SistemaCurricularEntities context)
        {
            var model = this.CreateModel(context);
            context.AddToVaga(model);
            return model;
        }

        private DataAccess.Vaga Update(DataAccess.SistemaCurricularEntities context)
        {
            return this.CreateModel(context);
        }

        private DataAccess.Vaga CreateModel(SistemaCurricularEntities context)
        {
            DataAccess.Vaga vaga = null;
            if (this.IsNew)
                vaga = new DataAccess.Vaga();
            else
            {
                vaga = context.Vaga.FirstOrDefault(f => f.VagaId == this.VagaId);
                if (vaga == null)
                    throw new Exception("Código de vaga inválido, não foi possivel localizar a vaga informada");
                this.DataCadastro = vaga.DataCadastro;
            }
            vaga.Ativo = this.Ativo;
            vaga.CargoId = this.CargoId;
            vaga.DataCadastro = this.DataCadastro;
            vaga.Disponibilidade = this.Disponibilidade;
            vaga.QtdVagas = this.QtdVagas;
            vaga.SalarioOfertado = this.SalarioOferecido;
            vaga.Status = this.Status;
            vaga.UsuarioRepresentanteId = this.UsuarioId;
            vaga.VagaId = this.VagaId;
            vaga.Observacoes = this.Observacoes;
            vaga.DataInicioInscricao = this.DataInicioInscricao;
            vaga.DataFimInscricao = this.DataFimInscricao;
            vaga.TipoVaga = this.TipoVaga;
            return vaga;
        }

        public bool AdicionarIdioma(Idioma idioma)
        {
            bool retorno = false;
            Transaction.Begin((context) =>
            {
                
                context.IdiomaVaga.AddObject(new IdiomaVaga(){
                    IdiomaId = idioma.IdiomaId,
                    VagaId = this.VagaId,
                    Nivel = idioma.Nivel
                });

                retorno = true;
                return true;
            }).OnError(exception =>
            {
                throw exception;
            }).OnSuccess(() =>
            {

            });
            return retorno;
        }

        public bool RemoverIdioma(Idioma idioma)
        {
            bool retorno = false;
            Transaction.Begin((context) =>
            {
                var idiomaVaga = context.IdiomaVaga.FirstOrDefault(f => f.IdiomaId == idioma.IdiomaId && f.VagaId == this.VagaId);
                if (idiomaVaga == null)
                    throw new Exception("Idioma não cadastrado para a vaga");
                context.IdiomaVaga.DeleteObject(idiomaVaga);

                retorno = true;
                return true;
            }).OnError(exception =>
            {
                throw exception;
            }).OnSuccess(() =>
            {

            });
            return retorno;
        }

        public static List<Vaga> Listar(Vaga vaga)
        {
            if (vaga == null)
                vaga = new Vaga();
            bool pesquisaCargo = vaga.Cargo != null;
            string cargo = "";
            if(pesquisaCargo)
                cargo = vaga.Cargo.Nome;
            var context = new DataAccess.SistemaCurricularEntities();
            bool pesquisaDataAbertura = vaga.DataInicioInscricao > DateTime.MinValue;
            var lista = context.Vaga.Where(a => 
                        (vaga.VagaId == 0 || a.VagaId == vaga.VagaId) &&
                        (vaga.UsuarioId == 0 || vaga.UsuarioId == a.UsuarioRepresentanteId) &&
                        (!pesquisaCargo || (cargo == null || a.Cargo.Nome.Contains(cargo))) &&
                        (vaga.TipoVaga == null || vaga.TipoVaga == "" || vaga.TipoVaga == a.TipoVaga)                        
                    ).ToList().Select(s => vaga.Create(s)).ToList();
            return lista;
        }

        public static List<Vaga> ObterVagasAbertasParaInscricao(TipoVaga tipo, long usuarioLogadoId = 0)
        {
            var context = new DataAccess.SistemaCurricularEntities();
            var dtIni = DateTime.Now.Date;
            var i = Lib.TipoVaga.Interno;
            var tipoVaga = tipo == Lib.TipoVaga.InternoExterno ? "" : ((int)tipo).ToString();
            return context.Vaga
                .Where(
                    w =>
                        w.Ativo &&
                        w.Status != 2 &&
                        w.DataInicioInscricao <=  dtIni && 
                        w.DataFimInscricao >= dtIni &&
                        (w.TipoVaga == "" || w.TipoVaga == tipoVaga) &&
                        (usuarioLogadoId == 0 || !w.Indicacao.Any(a => a.UsuarioIndicadoId == usuarioLogadoId))
                ).ToList()
                .Select(s => new Vaga().Create(s))
                .ToList();
        }

        internal Vaga Create(DataAccess.Vaga item)
        {
            var vaga = new Vaga();
            vaga.VagaId = item.VagaId;
            vaga.QtdVagas = item.QtdVagas;
            vaga.SalarioOferecido = item.SalarioOfertado;
            vaga.Ativo = item.Ativo;
            vaga.Cargo = new Cargo().Create(item.Cargo);
            vaga.CargoId = item.CargoId;
            vaga.DataCadastro = item.DataCadastro;
            vaga.Disponibilidade = item.Disponibilidade;
            vaga.Status = item.Status;
            vaga.UsuarioId = item.UsuarioRepresentanteId;
            vaga.Usuario = new Usuario().Create(item.Usuario);
            vaga.Observacoes = item.Observacoes;
            vaga.DataInicioInscricao = item.DataInicioInscricao;
            vaga.DataFimInscricao = item.DataFimInscricao;
            vaga.TipoVaga = item.TipoVaga;
            return vaga;
        }

        public List<Idioma> ListarIdiomas()
        {
            var lista = new DataAccess.SistemaCurricularEntities().IdiomaVaga.Where(
                        f => f.VagaId == this.VagaId
                    ).ToList().Select(s => new Lib.Idioma().Create(s.Idioma)).ToList();

            return lista;
        }

        public bool AdicionarFormacao(Formacao formacao)
        {
            bool retorno = false;
            Transaction.Begin((context) =>
            {

                var vaga = context.Vaga.FirstOrDefault(f => f.VagaId == this.VagaId);
                var curso = context.Curso.FirstOrDefault(f => formacao.CursoId == f.CursoId);
                if(vaga == null)
                    throw new Exception("Vaga inválida; objeto não pode ser nulo");
                if (curso == null)
                    throw new Exception("Curso inválido; objeto não pode ser nulo");
                vaga.Curso.Add(curso);
                retorno = true;
                return true;
            }).OnError(exception =>
            {
                throw exception;
            }).OnSuccess(() =>
            {

            });
            return retorno;
        }

        public bool RemoverFormacao(Formacao formacao)
        {
            bool retorno = false;
            Transaction.Begin((context) =>
            {
                var vaga = context.Vaga.FirstOrDefault(f => f.VagaId == this.VagaId);
                var curso = context.Curso.FirstOrDefault(f => f.CursoId == formacao.CursoId);
                if (vaga == null)
                    throw new Exception("Vaga inválida; objeto não pode ser nulo");
                if (curso == null)
                    throw new Exception("Curso inválido; objeto não pode ser nulo");
                vaga.Curso.Remove(curso);
                retorno = true;
                return true;
            }).OnError(exception =>
            {
                throw exception;
            }).OnSuccess(() =>
            {

            });
            return retorno;
        }

        public List<Curso> ListarCursos()
        {
            DataAccess.SistemaCurricularEntities context = new SistemaCurricularEntities();
            var vaga = context.Vaga.FirstOrDefault(f => f.VagaId == this.VagaId);
            if (vaga == null)
                return null;
            Curso curso = new Curso();
            return vaga.Curso.ToList().Select(s => curso.Create(s)).ToList();
        }

        public static Vaga Create(long vagaId)
        {
            var vaga = new Vaga();
            vaga = vaga.Create(new DataAccess.SistemaCurricularEntities().Vaga.FirstOrDefault(f => f.VagaId == vagaId));
            return vaga;
        }
    }
}
